/****************************************************************************
 * Copyright (c) 2016 - 2023 liangxiegame UNDER MIT License
 * 
 * https://qframework.cn
 * https://github.com/liangxiegame/QFramework
 * https://gitee.com/liangxiegame/QFramework
 ****************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace QFramework
{
    #region 条件系统
    
    /// <summary>
    /// 条件接口
    /// </summary>
    public interface ITransitionCondition
    {
        bool Evaluate(object context);
    }
    
    /// <summary>
    /// 简单条件（叶子节点）
    /// </summary>
    public class SimpleCondition : ITransitionCondition
    {
        private Func<object, bool> _func;
        public SimpleCondition(Func<object, bool> func) { _func = func; }
        public bool Evaluate(object context) => _func(context);
    }
    
    /// <summary>
    /// 与条件（组合节点）
    /// </summary>
    public class AndCondition : ITransitionCondition
    {
        public List<ITransitionCondition> Children = new List<ITransitionCondition>();
        public AndCondition(params ITransitionCondition[] children) { Children.AddRange(children); }
        public bool Evaluate(object context) => Children.All(c => c.Evaluate(context));
    }
    
    /// <summary>
    /// 或条件（组合节点）
    /// </summary>
    public class OrCondition : ITransitionCondition
    {
        public List<ITransitionCondition> Children = new List<ITransitionCondition>();
        public OrCondition(params ITransitionCondition[] children) { Children.AddRange(children); }
        public bool Evaluate(object context) => Children.Any(c => c.Evaluate(context));
    }
    
    /// <summary>
    /// 非条件（组合节点）
    /// </summary>
    public class NotCondition : ITransitionCondition
    {
        public ITransitionCondition Child;
        public NotCondition(ITransitionCondition child) { Child = child; }
        public bool Evaluate(object context) => !Child.Evaluate(context);
    }
    
    /// <summary>
    /// 条件注册表
    /// </summary>
    public static class ConditionRegistry
    {
        private static Dictionary<string, ITransitionCondition> registry = new Dictionary<string, ITransitionCondition>();
        
        public static void Register(string name, ITransitionCondition condition)
        {
            registry[name] = condition;
        }
        
        public static ITransitionCondition Get(string name)
        {
            return registry.TryGetValue(name, out var cond) ? cond : null;
        }
        
        public static void Clear()
        {
            registry.Clear();
        }
    }
    
    #endregion
    
    #region 配置表系统
    
    /// <summary>
    /// 状态切换配置
    /// </summary>
    [System.Serializable]
    public class StateTransitionConfig
    {
        public string ConditionName;
        public string TargetStateId;
        public bool IsForceTransition; // 是否强制切换（无视当前状态）
    }
    
    /// <summary>
    /// 状态配置
    /// </summary>
    [System.Serializable]
    public class StateConfig
    {
        public string StateId;
        public List<StateTransitionConfig> Transitions = new List<StateTransitionConfig>();
        public bool CanBeInterrupted = true; // 是否可被强制切换打断
    }
    
    /// <summary>
    /// 状态机配置
    /// </summary>
    [CreateAssetMenu(menuName = "FSM/StateMachineConfig")]
    public class StateMachineConfig : ScriptableObject
    {
        public List<StateConfig> States = new List<StateConfig>();
        public string InitialStateId;
    }
    
    #endregion
    
    #region 增强状态机
    
    /// <summary>
    /// 增强状态机（支持配置表驱动）
    /// </summary>·
    public class EnhancedFSM<TStateId> where TStateId : struct
    {
        private Dictionary<TStateId, IState> mStates = new Dictionary<TStateId, IState>();
        private Dictionary<string, TStateId> mStateNameToId = new Dictionary<string, TStateId>();
        private Dictionary<TStateId, StateConfig> mStateConfigs = new Dictionary<TStateId, StateConfig>();
        
        private IState mCurrentState;
        private TStateId mCurrentStateId;
        private object mContext; // 上下文对象
        
        public IState CurrentState => mCurrentState;
        public TStateId CurrentStateId => mCurrentStateId;
        public TStateId PreviousStateId { get; private set; }
        
        public long FrameCountOfCurrentState = 1;
        public float SecondsOfCurrentState = 0.0f;
        
        private Action<TStateId, TStateId> mOnStateChanged = (_, __) => { };
        
        public EnhancedFSM(object context = null)
        {
            mContext = context;
        }
        
        /// <summary>
        /// 添加状态
        /// </summary>
        public void AddState(TStateId id, IState state, StateConfig config = null)
        {
            mStates[id] = state;
            if (config != null)
            {
                mStateConfigs[id] = config;
                mStateNameToId[config.StateId] = id;
            }
        }
        
        /// <summary>
        /// 链式调用添加状态
        /// </summary>
        public CustomState State(TStateId id)
        {
            if (mStates.ContainsKey(id))
            {
                return mStates[id] as CustomState;
            }
            
            var state = new CustomState();
            mStates[id] = state;
            return state;
        }
        
        /// <summary>
        /// 从配置表加载状态机
        /// </summary>
        public void LoadFromConfig(StateMachineConfig config, Func<string, TStateId> nameToIdConverter)
        {
            foreach (var stateConfig in config.States)
            {
                var stateId = nameToIdConverter(stateConfig.StateId);
                mStateConfigs[stateId] = stateConfig;
                mStateNameToId[stateConfig.StateId] = stateId;
            }
        }
        
        /// <summary>
        /// 切换状态
        /// </summary>
        public void ChangeState(TStateId targetStateId)
        {
            if (targetStateId.Equals(CurrentStateId)) return;
            
            if (mStates.TryGetValue(targetStateId, out var state))
            {
                if (mCurrentState != null && state.Condition())
                {
                    PerformStateChange(targetStateId, state);
                }
            }
        }
        
        /// <summary>
        /// 强制切换状态（无视条件）
        /// </summary>
        public void ForceChangeState(TStateId targetStateId)
        {
            if (targetStateId.Equals(CurrentStateId)) return;
            
            if (mStates.TryGetValue(targetStateId, out var state))
            {
                // 检查当前状态是否可被打断
                if (mCurrentState != null && mStateConfigs.TryGetValue(CurrentStateId, out var currentConfig))
                {
                    if (!currentConfig.CanBeInterrupted)
                    {
                        Debug.LogWarning($"状态 {CurrentStateId} 不可被打断");
                        return;
                    }
                }
                
                PerformStateChange(targetStateId, state);
            }
        }
        
        private void PerformStateChange(TStateId newStateId, IState newState)
        {
            mCurrentState?.Exit();
            PreviousStateId = mCurrentStateId;
            mCurrentState = newState;
            mCurrentStateId = newStateId;
            mOnStateChanged?.Invoke(PreviousStateId, CurrentStateId);
            FrameCountOfCurrentState = 1;
            SecondsOfCurrentState = 0.0f;
            mCurrentState.Enter();
        }
        
        /// <summary>
        /// 开始状态
        /// </summary>
        public void StartState(TStateId stateId)
        {
            if (mStates.TryGetValue(stateId, out var state))
            {
                PreviousStateId = stateId;
                mCurrentState = state;
                mCurrentStateId = stateId;
                FrameCountOfCurrentState = 0;
                SecondsOfCurrentState = 0.0f;
                state.Enter();
            }
        }
        
        /// <summary>
        /// 更新状态机（包含配置表驱动的状态切换）
        /// </summary>
        public void Update()
        {
            mCurrentState?.Update();
            FrameCountOfCurrentState++;
            SecondsOfCurrentState += Time.deltaTime;
            
            // 检查配置表中的状态切换条件
            CheckConfigTransitions();
        }
        
        /// <summary>
        /// 检查配置表中的状态切换
        /// </summary>
        private void CheckConfigTransitions()
        {
            if (mCurrentState == null || !mStateConfigs.TryGetValue(CurrentStateId, out var config))
                return;
                
            foreach (var transition in config.Transitions)
            {
                var condition = ConditionRegistry.Get(transition.ConditionName);
                if (condition != null && condition.Evaluate(mContext))
                {
                    if (transition.IsForceTransition)
                    {
                        // 强制切换
                        if (mStateNameToId.TryGetValue(transition.TargetStateId, out var targetId))
                        {
                            ForceChangeState(targetId);
                        }
                    }
                    else
                    {
                        // 普通切换
                        if (mStateNameToId.TryGetValue(transition.TargetStateId, out var targetId))
                        {
                            ChangeState(targetId);
                        }
                    }
                    break;
                }
            }
        }
        
        public void FixedUpdate()
        {
            mCurrentState?.FixedUpdate();
        }
        
        public void OnGUI()
        {
            mCurrentState?.OnGUI();
        }
        
        public void OnStateChanged(Action<TStateId, TStateId> onStateChanged)
        {
            mOnStateChanged += onStateChanged;
        }
        
        public void Clear()
        {
            mCurrentState = null;
            mCurrentStateId = default;
            mStates.Clear();
            mStateConfigs.Clear();
            mStateNameToId.Clear();
        }
    }
    
    #endregion
    
    #region 使用示例
    
    /// <summary>
    /// 玩家状态机示例
    /// </summary>
    public class PlayerStateMachineExample : MonoBehaviour
    {
        public enum PlayerState
        {
            Idle,
            Run,
            Jump,
            Attack,
            Hurt,
            Dead
        }
        
        public EnhancedFSM<PlayerState> FSM;
        public StateMachineConfig Config;
        
        // 玩家属性
        public bool IsInAir = false;
        public bool IsDashOnCooldown = false;
        public int DashCount = 0;
        public int DashLimit = 3;
        public bool IsHit = false;
        public int Health = 100;
        
        void Start()
        {
            FSM = new EnhancedFSM<PlayerState>(this);
            
            // 注册条件
            RegisterConditions();
            
            // 从配置表加载
            if (Config != null)
            {
                FSM.LoadFromConfig(Config, stateName => 
                {
                    return (PlayerState)Enum.Parse(typeof(PlayerState), stateName);
                });
            }
            
            // 添加状态
            SetupStates();
            
            // 开始状态
            FSM.StartState(PlayerState.Idle);
        }
        
        void RegisterConditions()
        {
            // 简单条件
            ConditionRegistry.Register("IsInAir", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir));
            ConditionRegistry.Register("IsDashKeyPressed", new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.LeftShift)));
            ConditionRegistry.Register("IsDashOnCooldown", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsDashOnCooldown));
            ConditionRegistry.Register("IsDashLimitReached", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount >= ((PlayerStateMachineExample)ctx).DashLimit));
            ConditionRegistry.Register("IsHit", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsHit));
            ConditionRegistry.Register("IsDead", new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).Health <= 0));
            ConditionRegistry.Register("IsRunKeyPressed", new SimpleCondition(ctx => Input.GetKey(KeyCode.D)));
            ConditionRegistry.Register("IsAttackKeyPressed", new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.A)));
            
            // 复杂条件组合
            ConditionRegistry.Register("CanDashInAir", new AndCondition(
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir),
                new SimpleCondition(ctx => Input.GetKeyDown(KeyCode.LeftShift)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsDashOnCooldown)),
                new NotCondition(new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount >= ((PlayerStateMachineExample)ctx).DashLimit))
            ));
            
            ConditionRegistry.Register("RecoverDashOnHitInAir", new AndCondition(
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsInAir),
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).IsHit),
                new SimpleCondition(ctx => ((PlayerStateMachineExample)ctx).DashCount == ((PlayerStateMachineExample)ctx).DashLimit)
            ));
        }
        
        void SetupStates()
        {
            // Idle 状态
            FSM.State(PlayerState.Idle)
                .OnEnter(() => Debug.Log("进入Idle"))
                .OnUpdate(() =>
                {
                    // 可以在这里处理输入，但主要依赖配置表驱动
                })
                .OnExit(() => Debug.Log("离开Idle"));
            
            // Run 状态
            FSM.State(PlayerState.Run)
                .OnEnter(() => Debug.Log("进入Run"))
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Run"));
            
            // Jump 状态
            FSM.State(PlayerState.Jump)
                .OnEnter(() => Debug.Log("进入Jump"))
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Jump"));
            
            // Attack 状态
            FSM.State(PlayerState.Attack)
                .OnEnter(() => Debug.Log("进入Attack"))
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Attack"));
            
            // Hurt 状态（可被打断）
            FSM.State(PlayerState.Hurt)
                .OnEnter(() => 
                {
                    Debug.Log("进入Hurt");
                    IsHit = false; // 重置受击标志
                })
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Hurt"));
            
            // Dead 状态（不可被打断）
            FSM.State(PlayerState.Dead)
                .OnEnter(() => Debug.Log("进入Dead"))
                .OnUpdate(() => { })
                .OnExit(() => Debug.Log("离开Dead"));
        }
        
        void Update()
        {
            FSM.Update();
            
            // 测试输入
            if (Input.GetKeyDown(KeyCode.H))
            {
                IsHit = true;
            }
            
            if (Input.GetKeyDown(KeyCode.K))
            {
                Health = 0;
            }
        }
        
        void OnGUI()
        {
            FSM.OnGUI();
            
            GUILayout.Label($"当前状态: {FSM.CurrentStateId}");
            GUILayout.Label($"生命值: {Health}");
            GUILayout.Label($"冲刺次数: {DashCount}/{DashLimit}");
            GUILayout.Label("按 H 受击，按 K 死亡");
        }
        
        void OnDestroy()
        {
            FSM.Clear();
            ConditionRegistry.Clear();
        }
    }
    
    #endregion
} 